package com.bascker.algorithm.practice.arr;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组（的长度）。
 *
 * For example: <p>
 *   in: [0,1],     out: 2
 *   in: [0,1,0]    out: 2
 *
 * Note: 因为是二进制数组，所以只包含 0 和 1
 *
 * @author bascker
 * @apiNote from leetcode T525
 */
public class FindMaxLength {

    /**
     * 前缀和 + hashmap
     */
    public int findMaxLength(int[] nums) {
        if (Objects.isNull(nums)) {
            return 0;
        }

        int n = nums.length;
        Map<Integer, Integer> map = new HashMap<>();
        // 初始时前缀和为 0 的位置为 -1
        map.put(0, -1);
        int preSum = 0;
        int max = 0;

        for (int i = 0; i < n; i ++) {
            int x = nums[i];
            // 若 x 是 0，则前缀和 -1，若是 1，则前缀和 + 1
            preSum += (x == 0 ? - 1 : 1);

            // 遇到相同的前缀和
            if (map.containsKey(preSum)) {
                // i - map.get(preSum)：两个相同前缀和之前的 0、1数量是相同的
                max = Math.max(max, i - map.get(preSum));
            }
            // 还没有记录的前缀和，就压栈(也只记录最早/第一次出现的前缀和)
            else {
                map.put(preSum, i);
            }
        }

        return max;
    }

    /**
     * 暴力解法: TLE
     */
    @Deprecated
    private int tle(int[] nums) {
        if (Objects.isNull(nums) || nums.length < 2) {
            return 0;
        }

        int n = nums.length;
        int max = 0;
        for (int i = 0; i < n; i ++) {
            int[] count = new int[2];
            for (int j = i; j < n; j ++) {
                count[nums[j]] ++;

                if(count[0] == count[1]) {
                    max = Math.max(max, j - i + 1);
                }
            }
        }

        return max;
    }

}
